package com.xiaoshuidi.cloud.module.rooms.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaoshuidi.cloud.framework.common.exception.ErrorCode;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.module.contract.api.ContractApi;
import com.xiaoshuidi.cloud.module.contract.vo.RenterVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomdevice.vo.DepRoomVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomdevice.vo.MeterReadingVO;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomdevice.vo.PayModeMappingVo;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.roomdevice.vo.RoomSdiotPayModeMappingVO;
import com.xiaoshuidi.cloud.module.rooms.enums.DeviceTypeEnum;
import com.xiaoshuidi.cloud.module.rooms.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.rooms.mapper.*;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomDevicePrice;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomSdiotPayModeConfig;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomSdiotPayModeMapping;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomSdiotReadingOrder;
import com.xiaoshuidi.cloud.module.rooms.repository.IotRoomDevicePriceRepository;
import com.xiaoshuidi.cloud.module.rooms.service.RoomSdiotPayModeMappingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class RoomSdiotPayModeMappingServiceImpl extends ServiceImpl<RoomSdiotPayModeMappingMapper, RoomSdiotPayModeMapping> implements RoomSdiotPayModeMappingService {

    private final RoomSdiotPayModeMappingMapper roomSdiotPayModeMappingMapper;

    private final RoomSdiotPayModeConfigMapper roomSdiotPayModeConfigMapper;

    private final RoomSdiotReadingOrderMapper roomSdiotReadingOrderMapper;

    private final ContractApi contractApi;

    @Autowired
    private RoomDevicePriceAssociationMapper roomDevicePriceAssociationMapper;

    @Autowired
    private RoomDevicePriceMapper roomDevicePriceMapper;

    @Autowired
    private IotRoomDevicePriceRepository iotRoomDevicePriceRepository;

    @Override
    @Transactional(rollbackFor = {Exception.class})
    public CommonResult<String> saveRoomSdiotPayMode(RoomSdiotPayModeMappingVO roomSdiotPayModeMappingVO) {
        // todo @黄光辉 不要在循环里面疯狂的保存数据库; 需要优化
        RoomSdiotPayModeConfig roomSdiotPayModeConfig = roomSdiotPayModeConfigMapper.selectById(roomSdiotPayModeMappingVO.getPayModeConfigId());
        List<Long> roomHouseList = roomSdiotPayModeMappingVO.getList();
        if (CollectionUtil.isNotEmpty(roomHouseList)) {
            for (Long roomHouseId : roomHouseList) {
                QueryWrapper<RoomSdiotPayModeMapping> qw = new QueryWrapper<>();
                qw.eq("room_house_id", roomHouseId).eq("fee_type", roomSdiotPayModeConfig.getFeeType()).ne("pay_mode", roomSdiotPayModeConfig.getPayMode());
                List<RoomSdiotPayModeMapping> list = roomSdiotPayModeMappingMapper.selectList(qw);
                if (CollectionUtil.isNotEmpty(list)) {
                    List<MeterReadingVO> roomName = roomSdiotPayModeMappingMapper.findRoomName(roomHouseId);
                    MeterReadingVO meterReadingVO = roomName.get(0);
                    if (meterReadingVO.getIsConcentrated()) {
                        String finalName = meterReadingVO.getArea() + "小区" + meterReadingVO.getBuildingNo() + "栋" + meterReadingVO.getHouseNo();
                        return CommonResult.error(ErrorCodeConstants.HOUSE_PAY_MODE_REPEAT.getCode(), finalName + ErrorCodeConstants.HOUSE_PAY_MODE_REPEAT.getMsg());
                    } else {
                        String finalName = meterReadingVO.getArea() + meterReadingVO.getBuildingNo() + "栋" + meterReadingVO.getUnitNo() + "单元" + meterReadingVO.getHouseNo();
                        return CommonResult.error(ErrorCodeConstants.HOUSE_PAY_MODE_REPEAT.getCode(), finalName + ErrorCodeConstants.HOUSE_PAY_MODE_REPEAT.getMsg());
                    }

                }
            }
        }

//        QueryWrapper<RoomSdiotPayModeMapping> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("pay_mode_config_id", roomSdiotPayModeMappingVO.getPayModeConfigId());
//        roomSdiotPayModeMappingMapper.delete(queryWrapper);

        roomSdiotPayModeMappingMapper.updatePayModeMapping(roomSdiotPayModeMappingVO.getApartmentId(),roomSdiotPayModeMappingVO.getPayModeConfigId());


        if (CollectionUtil.isNotEmpty(roomHouseList)) {
            List<RoomSdiotPayModeMapping> mappings = new ArrayList<>();
            for (Long roomHouseId : roomHouseList) {
                RoomSdiotPayModeMapping roomSdiotPayModeMapping = new RoomSdiotPayModeMapping();
                roomSdiotPayModeMapping.setPayMode(roomSdiotPayModeConfig.getPayMode());
                roomSdiotPayModeMapping.setFeeType(roomSdiotPayModeConfig.getFeeType());
                roomSdiotPayModeMapping.setUniqueNumber(roomHouseId.toString() + roomSdiotPayModeConfig.getFeeType());
                roomSdiotPayModeMapping.setPayModeConfigId(roomSdiotPayModeMappingVO.getPayModeConfigId());
                roomSdiotPayModeMapping.setRoomHouseId(roomHouseId);
                roomSdiotPayModeMapping.setDeptId(roomSdiotPayModeMappingVO.getDeptId());
                mappings.add(roomSdiotPayModeMapping);
            }
            this.saveBatch(mappings);
        }

        if (roomSdiotPayModeConfig.getPayMode().equals(DeviceTypeEnum.PAY_MODE_BEHIND.getName())) {
            QueryWrapper<RoomSdiotPayModeMapping> qw = new QueryWrapper<>();
            qw.eq("pay_mode", DeviceTypeEnum.PAY_MODE_BEHIND.getName());
            List<RoomSdiotPayModeMapping> list = roomSdiotPayModeMappingMapper.selectList(qw);
            List<RoomSdiotReadingOrder> roomSdiotReadingOrders = roomSdiotReadingOrderMapper.selectList(null);
            //批量抄表单有，后付费应用房源没有（批量抄表单删除）
            List<RoomSdiotReadingOrder> deleteCollect = roomSdiotReadingOrders.stream().filter(roomSdiotReadingOrder -> !list.stream().map(roomSdiotPayModeMapping -> roomSdiotPayModeMapping.getUniqueNumber()).collect(Collectors.toList()).contains(roomSdiotReadingOrder.getUniqueNumber()))
//                            .filter(roomSdiotReadingOrder -> !list.stream().map(RoomSdiotPayModeMapping::getFeeType).collect(Collectors.toList()).contains(roomSdiotReadingOrder.getFeeType()))
                    .collect(Collectors.toList());

            for (RoomSdiotReadingOrder roomSdiotReadingOrder : deleteCollect) {
                roomSdiotReadingOrderMapper.deleteById(roomSdiotReadingOrder.getId());
            }
            //后付费应用房源有，批量抄表单没有（批量抄表单增加）
            List<RoomSdiotPayModeMapping> addCollect = list.stream().filter(roomSdiotPayModeMapping -> !roomSdiotReadingOrders.stream().map(RoomSdiotReadingOrder::getUniqueNumber).collect(Collectors.toList()).contains(roomSdiotPayModeMapping.getUniqueNumber()))
//                            .filter(roomSdiotPayModeMapping -> !roomSdiotReadingOrders.stream().map(RoomSdiotReadingOrder::getFeeType).collect(Collectors.toList()).contains(roomSdiotPayModeMapping.getFeeType()))
                    .collect(Collectors.toList());
            for (RoomSdiotPayModeMapping roomSdiotPayModeMapping : addCollect) {
                MeterReadingVO meterReadingVO = roomSdiotPayModeMappingMapper.findMeterReadingVO(roomSdiotPayModeMapping.getRoomHouseId(), roomSdiotPayModeMapping.getFeeType(), roomSdiotPayModeMapping.getPayMode());
                Boolean isConcentrated = meterReadingVO.getIsConcentrated();

                String area = meterReadingVO.getArea();
                String buildingNo = meterReadingVO.getBuildingNo();
                String unitNo = meterReadingVO.getUnitNo();
                String houseNo = meterReadingVO.getHouseNo();
                String finalName = null;
                if (isConcentrated) {
                    finalName = area + "小区" + buildingNo + "栋" + houseNo;
                } else {
                    finalName = area + buildingNo + "栋" + unitNo + "单元" + houseNo;
                }
                RoomSdiotReadingOrder roomSdiotReadingOrder = new RoomSdiotReadingOrder();
                roomSdiotReadingOrder.setRoomName(finalName);
                roomSdiotReadingOrder.setRoomHouseId(roomSdiotPayModeMapping.getRoomHouseId());
                log.info("获取租客姓名##############");
                CommonResult<RenterVO> voCommonResult = contractApi.getContractRenterInfoByRoomId(roomSdiotPayModeMapping.getRoomHouseId());
                Integer code = voCommonResult.getCode();
                ErrorCode contractNotExists = com.xiaoshuidi.cloud.module.contract.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS;
                if (Objects.equals(code, contractNotExists.getCode())) {
                    throw new ServiceException(contractNotExists.getCode(), finalName + contractNotExists.getMsg());
                }
                String customerName = voCommonResult.getData().getCustomerName();
                log.info("获取租客姓名##############");

                roomSdiotReadingOrder.setTenantName(customerName);

                roomSdiotReadingOrder.setFeeType(roomSdiotPayModeMapping.getFeeType());
                RoomDevicePrice deviceByRoomId = iotRoomDevicePriceRepository.getDeviceByRoomId(roomSdiotPayModeMapping.getRoomHouseId());
                if (ObjectUtil.isEmpty(deviceByRoomId)) {
                    throw new ServiceException(ErrorCodeConstants.HOUSE_DEVICE_PRICE.getCode(), finalName + ErrorCodeConstants.HOUSE_DEVICE_PRICE.getMsg());
                }
                if (DeviceTypeEnum.AMMETER_FEE_TYPE.getName().equals(roomSdiotPayModeMapping.getFeeType())) {
                    roomSdiotReadingOrder.setPrice(new BigDecimal(deviceByRoomId.getElectricityPrice() + ""));
                } else if (DeviceTypeEnum.COLDWATER_FEE_TYPE.getName().equals(roomSdiotPayModeMapping.getFeeType())) {
                    roomSdiotReadingOrder.setPrice(new BigDecimal(deviceByRoomId.getColdWorterPrice() + ""));
                } else if (DeviceTypeEnum.HOTWATER_FEE_TYPE.getName().equals(roomSdiotPayModeMapping.getFeeType())) {
                    roomSdiotReadingOrder.setPrice(new BigDecimal(deviceByRoomId.getHotWorterPrice() + ""));
                }
                roomSdiotReadingOrder.setUniqueNumber(roomSdiotPayModeMapping.getUniqueNumber());
                roomSdiotReadingOrderMapper.insert(roomSdiotReadingOrder);
            }
        }
        return CommonResult.success("付费模式应用到该房源成功");
    }

    @Override
    public List<DepRoomVO> findPayModeHouseRoomId(long payModeConfigId) {
        List<DepRoomVO> voList = new ArrayList<>();
        QueryWrapper<RoomSdiotPayModeMapping> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("rsdpa.pay_mode_config_id", payModeConfigId)
                .eq("rsdpa.deleted", false);
        List<PayModeMappingVo> list = roomSdiotPayModeMappingMapper.getPayModeMappingList(queryWrapper);
        Map<Long, DepRoomVO> hashMap = new HashMap<>();
        for (PayModeMappingVo roomSdiotPayModeMapping : list) {
            Long roomHouseId = roomSdiotPayModeMapping.getRoomHouseId();
            Long apartmentId = roomSdiotPayModeMapping.getApartmentId();
            if (hashMap.containsKey(apartmentId)) {
                hashMap.get(apartmentId).getList().add(roomHouseId);
                hashMap.get(apartmentId).setDeptId(apartmentId);
                hashMap.put(apartmentId, hashMap.get(apartmentId));
            } else {
                DepRoomVO depRoomVO = new DepRoomVO();
                depRoomVO.setApartmentId(apartmentId);
                List<Long> longList = new ArrayList<>();
                longList.add(roomHouseId);
                depRoomVO.setList(longList);
                hashMap.put(apartmentId, depRoomVO);
            }

        }
        Set<Map.Entry<Long, DepRoomVO>> entries = hashMap.entrySet();
        for (Map.Entry<Long, DepRoomVO> entry : entries) {
            DepRoomVO value = entry.getValue();
            voList.add(value);
        }
        return voList;
    }

    @Override
    public MeterReadingVO getModeMappingByRoomId(Long roomHouseId, String feeType) {
        return roomSdiotPayModeMappingMapper.getModeMappingByRoomId(roomHouseId, feeType);
    }
}
